perm filename ISSUES.2[COM,LSP] blob sn#874736 filedate 1989-06-23 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00007 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	∂23-Jun-89  1049	X3J13-mailer 	Issue: ADJUST-ARRAY-NOT-ADJUSTABLE (version 11)    
C00022 00003	∂23-Jun-89  1049	X3J13-mailer 	Issue: DATA-IO (version 8)
C00042 00004	∂23-Jun-89  1050	X3J13-mailer 	Issue: MAP-INTO (version 3)    
C00049 00005	∂23-Jun-89  1051	X3J13-mailer 	Issue: PATHNAME-LOGICAL (version 4) 
C00103 00006	∂23-Jun-89  1052	X3J13-mailer 	Issue: PATHNAME-WILD (version 7)    
C00131 00007	∂23-Jun-89  1234	X3J13-mailer 	issue CLOS-MACRO-COMPILATION, version 5  
C00144 ENDMK
C⊗;
∂23-Jun-89  1049	X3J13-mailer 	Issue: ADJUST-ARRAY-NOT-ADJUSTABLE (version 11)    
Received: from STONY-BROOK.SCRC.Symbolics.COM by SAIL.Stanford.EDU with TCP; 23 Jun 89  10:49:01 PDT
Received: from KENNETH-WILLIAMS.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via INTERNET with SMTP id 616029; 23 Jun 89 13:50:43 EDT
Date: Fri, 23 Jun 89 13:49 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Issue: ADJUST-ARRAY-NOT-ADJUSTABLE (version 11)
To: X3J13@sail.stanford.edu
Message-ID: <19890623174903.2.MOON@KENNETH-WILLIAMS.SCRC.Symbolics.COM>

Version 5 of this proposal passed with amendments at the January
1989 X3J13 meeting.  However, the amendments were found to result
in an inconsistent proposal, and it was also pointed out that some
related problems with simple-arrays were not addressed.  Since then
there has been a great deal of private discussion, and review of
various versions of the proposal including ones earlier than 5.

The result is this proposal, which is believed to be acceptable to
everyone and is being offered for a vote in June to replace the
January version that was already voted in.

This version has been amended based on last minute discussion: the
statement that ADJUST-ARRAY, when it copies, can destroy the original has
been removed.  A remark about VECTOR-PUSH-EXTEND has been added.  These
changes are in points 4 and f.  In the discussion section I mentioned
suggestions to get rid of ADJUSTABLE-ARRAY-P.


Issue:        ADJUST-ARRAY-NOT-ADJUSTABLE
References:   ADJUST-ARRAY (p297), ADJUSTABLE-ARRAY-P (p293),
              MAKE-ARRAY (pp286-289), simple arrays (p28, 289),
              simple strings with fill pointers (p299),
              VECTOR-PUSH-EXTEND (p296)
Category:     CLARIFICATION and CHANGE
Edit history: 22-Apr-87, Version 1 by Pitman
              15-Nov-88, Versions 2a,2b,2c by Pitman
              02-Dec-88, Version 3 by Pitman
              11-Jan-89, Version 4 by Pitman
              16-Jan-89, Version 5, by Gabriel.  Amended at the meeting to shorten.
              23-Jan-89, Version 6, by Moon.  Shorten without the bug introduced
                        by the amendment, add clarification of SIMPLE-ARRAY type.
              15-Feb-89, Version 7, by Pitman. Minor changes per comments from
                        RPG and Dalton.
              11-Mar-89, Version 8, by Pitman. Change category, add endorsements.
              17-Mar-89, Version 9, by Moon, fix wording and examples to make it
                        clear that the semantics of simple-array is unchanged.
               6-Jun-89, Version 10, by Moon and Gabriel, do over.
              23-Jun-89, Version 11, by Moon, two little corrections

Problem Description:

  There are a number of unclear passages in CLtL related to simple arrays
  and adjustable arrays.  There is disagreement on precisely how these
  passages are to be interpreted, and no one is happy with the fact that
  ADJUST-ARRAY works only on an implementation-dependent subset of arrays.

  The description of the :ADJUSTABLE option to MAKE-ARRAY on p288 says that
  ``the argument, if specified and not NIL, indicates that it must be
  possible to alter the array's size dynamically after it is created. This
  argument defaults to NIL.''  The description of the :ADJUSTABLE option
  does not say what MAKE-ARRAY will do if the argument is unsupplied or
  explicitly NIL.

  The description of ADJUSTABLE-ARRAY-P on p293 says that it is true ``if
  the argument (which must be an array) is adjustable, and otherwise
  false.'' However, the description of MAKE-ARRAY makes it clear that this
  is not necessarily the same as asking if the array was created with
  :ADJUSTABLE T.  If ADJUSTABLE-ARRAY-P returns NIL, you know that
  :ADJUSTABLE NIL was supplied (or no :ADJUSTABLE option was supplied), but
  if ADJUSTABLE-ARRAY-P returns T, then there is no information about
  whether :ADJUSTABLE was used.

  The description of ADJUST-ARRAY on pp297-298 says that it is ``not
  permitted to call ADJUST-ARRAY on an array that was not created with the
  :ADJUSTABLE option.'' This is inconsistent with ADJUSTABLE-ARRAY-P.

  The definition of SIMPLE-ARRAY on p.28 says ``an array that is not
  displaced to another array, has no fill pointer, and is not to have its
  size adjusted dynamically after creation is called a simple array.''
  It is left unclear whether this is an implication or an equivalence,
  i.e. whether there can be other simple arrays as well.
  CLtL p.299 appears to refer to simple strings with fill pointers,
  suggesting that it is an implication, but similar language is used for
  equivalences in other parts of CLtL.

Proposal (ADJUST-ARRAY-NOT-ADJUSTABLE:IMPLICIT-COPY)

  1. If MAKE-ARRAY is called with the :ADJUSTABLE, :FILL-POINTER, 
  and :DISPLACED-TO arguments each either unspecified or false, the
  resulting array is a simple array.  (This just repeats what CLtL
  says on page 289, it's here to aid in understanding the next point.)
      
  2. If MAKE-ARRAY is called with one or more of the :ADJUSTABLE,
  :FILL-POINTER, or :DISPLACED-TO arguments true, whether the
  resulting array is simple is unspecified.

  3. It is permitted to call ADJUST-ARRAY on any array.  (Remove the
  restriction documented at the bottom of p.297.)

  4. If ADJUST-ARRAY is applied to an array created with :ADJUSTABLE true,
  the array returned is EQ to its first argument.  It is not specified
  whether ADJUST-ARRAY returns an array EQ to its first argument for any
  other arrays.  If the array returned by ADJUST-ARRAY is not EQ to its
  first argument, the original array is unchanged and does not share
  storage with the new array.

  5. The predicate ADJUSTABLE-ARRAY-P is true if and only if ADJUST-ARRAY
  will return a value EQ to this array when given this array as its first
  argument.

Clarifications and Logical Consequences:

  a. There is no specified way to create an array for which ADJUSTABLE-ARRAY-P
     definitely returns NIL.

  b. There is no specified way to create an array that is non-simple.

  c. The definition of SIMPLE-ARRAY on p.28 is taken to be an implication,
     not an equivalence.  This is either a clarification or a change depending
     on one's prior reading of that definition.

  d. The meaning of ADJUSTABLE-ARRAY-P is changed.

  e. As with such functions as DELETE and NCONC, textbooks should
     instruct programmers to be careful to receive the value returned by
     ADJUST-ARRAY, as it might not be EQ to the first argument.

  f. VECTOR-PUSH-EXTEND still signals an error if given a non-adjustable
     array.  ADJUST-ARRAY's new feature of making a copy cannot be used
     by VECTOR-PUSH-EXTEND, since there is no way to return the copy to
     the caller.

Rationale:

  Points 3 and 4 eliminate the problem of ADJUST-ARRAY only working on a
  subset of arrays, by changing it to work on all arrays.  It remains
  implementation-dependent whether the array is modified in place or
  copied, i.e. whether the result is EQ to the argument, however many other
  functions in Common Lisp have similar implementation-dependent behavior.
  Implementation-dependent storage allocation or reuse is considered
  more benign than implementation-dependent applicability of an operation.

  Point 3 recognizes that ADJUST-ARRAY offers features that are offered by
  no other function and which are useful in cases involving non-adjustable
  arrays (for what amounts to copying).  This change would allow an
  expression such as:

    (SETQ X (ADJUST-ARRAY X ...))

  to work reliably. Those desiring the old behavior could do:

    (IF (OR (NOT (ADJUSTABLE-ARRAY-P X))
            (NOT (EQUAL (ARRAY-RANK X) (LENGTH NEW-DIMENSIONS))))
        (ERROR "Array cannot be adjusted."))
  
  to get the old style error checking.

  Point 5 recycles the name ADJUSTABLE-ARRAY-P as a test for whether an
  array is adjusted in place or by copying.

  Point 2 preserves the raison d'etre of simple arrays, which is to provide
  a portable interface to implementation-dependent specialized arrays that
  trade decreased functionality for faster access.  A proposed alternative
  was to specify a way to create an array that is guaranteed not to be
  simple.  This would have made (typep (make-array ...) 'simple-array)
  return the same value in all implementations, but would have required
  large changes to some implementations and would be of little benefit to
  users.  Users need to know that certain arrays are simple, so they can
  put in declarations and get higher performance, but users have no need to
  be able to create arrays that are definitely non-simple (for lower
  performance) or definitely non-adjustable.

Examples:

  1. The following program is conforming.
  
    (defun double (a)
      (adjust-array a (* (length a) 2)))
  
    (double (make-array 30))

  2. The following program is conforming.  In no implementation is the
  type declaration violated.

    (let ((a (make-array 100)))
      (declare (simple-array a))
      (frob a))

  3. The following program is non-conforming.  The consequences of this
  program are undefined because the type declaration is violated in some
  implementations.

    (let ((a (make-array 100 :adjustable t)))
      (declare (simple-array a))
      (frob a))

Current Practice:

  Every correct CLtL implementation conforms to points 1 and 2.  It is
  unlikely that any implementation currently exists that conforms to points
  3, 4, and 5.  Points 3 and 4 involve additions to an implementation to
  support the copying form of ADJUST-ARRAY.  Point 5 may involve a change
  to ADJUSTABLE-ARRAY-P or may be able to use the existing implementation
  of the function.

  Symbolics Genera makes :ADJUSTABLE NIL arrays adjustable in most cases,
  and ignores adjustability in deciding whether an array is a SIMPLE-ARRAY.
  The arrays that are internally simple in Symbolics Genera are a different
  subset of arrays from the type SIMPLE-ARRAY, because simplicity in that
  implementation depends on the rank and total-size as well as on the
  fill-pointer and displacement, thus Genera does not use the type
  SIMPLE-ARRAY for anything.

  Lucid, IIM, Ibuki, and Symbolics Cloe make :ADJUSTABLE NIL arrays
  non-adjustable in all cases, and make every array non-simple that CLTL
  does not require to be simple.

  Macintosh Allegro Common Lisp v1.2 makes :ADJUSTABLE NIL arrays
  non-adjustable in all cases, makes all arrays of rank other than 1
  non-simple (violating point 1), and makes every array non-simple that
  CLTL does not require to be simple.

Cost to Implementors:

  The change to ADJUSTABLE-ARRAY-P is easy.  The change to ADJUST-ARRAY may
  involve some complex coding but should not be a large task.  No changes
  are required to anything connected with SIMPLE-ARRAY.

Cost to Users:

  None in code that does not call ADJUSTABLE-ARRAY-P.  This is a fully
  upward-compatible change from the user's standpoint.

Benefits:

  Programs that use simple arrays and/or adjust arrays will be easier
  to port, as the language specification for these features will be
  clearer.  More programs will be able to call ADJUST-ARRAY, as its use
  will not be restricted to a subset of arrays.

Non-Benefits:

  Users who expect adjusting arrays created with :ADJUSTABLE NIL to signal
  an error would not get the desired signal.  A few programs might have
  porting problems due to variation among implementations of whether the
  result of ADJUST-ARRAY is EQ to the first argument.

Aesthetics:

  Most people believe the status quo is unaesthetic.  Having an aspect of
  the language more clearly specified is an aesthetic improvement.
  Allowing ADJUST-ARRAY on all arrays is an aesthetic improvement.

Discussion:

  There are at least 110 messages of discussion preceding this version of the
  proposal.  It does not seem feasible to summarize them here.

  Dick Gabriel, Dave Moon, and Guy Steele support this proposal.

  Some commentors would like to get rid of ADJUSTABLE-ARRAY-P, since
  ADJUST-ARRAY now works on all arrays.  Other commentors have said that
  ADJUSTABLE-ARRAY-P is still needed in some applications, such as user
  written functions that behave like VECTOR-PUSH-EXTEND, and hence should
  be kept; the concept of "adjustable array" is still meaningful.

∂23-Jun-89  1049	X3J13-mailer 	Issue: DATA-IO (version 8)
Received: from STONY-BROOK.SCRC.Symbolics.COM by SAIL.Stanford.EDU with TCP; 23 Jun 89  10:49:27 PDT
Received: from KENNETH-WILLIAMS.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via INTERNET with SMTP id 616030; 23 Jun 89 13:51:22 EDT
Date: Fri, 23 Jun 89 13:49 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Issue: DATA-IO (version 8)
To: X3J13@sail.stanford.edu
Message-ID: <19890623174939.3.MOON@KENNETH-WILLIAMS.SCRC.Symbolics.COM>

This is a new issue.  It arose from an investigation of features
that are plausibly needed but missing from draft ANSI Common Lisp.
This issue seems sufficiently simple and noncontroversial that
I would like to see it on the agenda for the June X3J13 meeting.

This issue has been amended based on last minute discussion.  Clarify
that "readable" is defined in terms of "similar as constants" as
defined in issue CONSTANT-COMPILABLE-TYPES.  This modifies point 1a and
adds new points 1d, 1e, and 1f.  The interaction between *PRINT-READABLY*
and other printer control variables has been tightened; this modifies
point 1c and deletes the old points 1d and 1e.

Issue:          DATA-IO
References:     CLtL pp.360, 370, 382
Related issues: CONSTANT-COMPILABLE-TYPES
Category:       ADDITION
Edit history:   Version 1,  9-May-89, by Moon
                Version 2, 10-May-89, by Moon
                        (clarify ambiguities, add PRINT-UNREADABLE-OBJECT)
                Version 3, 18-May-89, by Moon (respond to KMP's comments)
                Version 4, 21-May-89, by Moon (almost-final cleanup)
                Version 5, 22-May-89, by Pitman (``never say never'')
                Version 6, 23-May-89, by Moon (final cleanup)
                Version 7, 18-Jun-89, by Moon (more fixes based on
                        discussion in the cleanup subcommittee)
                Version 8, 23-Jun-89, by Moon (fixes based on discussion)

Problem description:

  Storing data in textual form in files, as Lisp expressions, is common
  practice but has some pitfalls.  Files can be unreadable if #<...> syntax
  is written by the printer, or if the reader syntax or package varies
  between writing and reading.  Files of data intended to be carried from
  one Lisp implementation to another can fail to read correctly if
  implementation-dependent syntax extensions get used when not intended.

  CLtL p.370 recommends that unreadable objects be printed with #<...>
  syntax including implementation-dependent information.  Now that users
  can write their own PRINT-OBJECT methods, a way is needed for such
  methods to print this syntax without any implementation-dependent coding.

Proposal (DATA-IO:ADD-SUPPORT):

  1a. Add a new variable *PRINT-READABLY*.  Add a corresponding keyword
  argument :READABLY to WRITE.  The default value of *PRINT-READABLY* is
  NIL.  If *PRINT-READABLY* is true, then printing any object produces a
  printed representation that the reader will accept.  The reader will
  produce an object that is "similar as a constant" to the object that
  was printed.  The term "similar as a constant" is defined in the
  already accepted compiler issue CONSTANT-COMPILABLE-TYPES:SPECIFY.

  If *PRINT-READABLY* is true and printing a readable printed
  representation is not possible, the printer signals an error of type
  PRINT-NOT-READABLE rather than using an unreadable syntax such as #<...>.
  The printed representation produced when *PRINT-READABLY* is true might
  or might not be the same as the printed representation produced when
  *PRINT-READABLY* is false.

  1b. All methods for PRINT-OBJECT must obey *PRINT-READABLY*.  This
  includes both user-defined methods and implementation-defined methods.

  1c. If *PRINT-READABLY* is true and another printer control variable
  (*PRINT-LENGTH*, *PRINT-LEVEL*, *PRINT-ESCAPE*, *PRINT-GENSYM*,
  *PRINT-ARRAY*, or an implementation-defined printer control variable)
  would cause the requirements of point 1a to be violated, that other
  printer control variable is ignored.

  1d. The printing of interned symbols is not affected by *PRINT-READABLY*,
  regardless of the outcome of issue COMPILE-FILE-SYMBOL-HANDLING
  (referenced by issue CONSTANT-COMPILABLE-TYPES).

  1e. Note that the "similar as a constant" rule for readable printing
  implies that #A or #( syntax cannot be used for arrays of element-type
  other than T.  An implementation will have to use another syntax or
  signal a PRINT-NOT-READABLE error.  A PRINT-NOT-READABLE error will not
  be signalled for strings or bit-vectors.

  1f. Readable printing of structures and standard-objects is controlled
  by their PRINT-OBJECT method, not by their MAKE-LOAD-FORM method.
  "Similarity as a constant" for these objects is application dependent
  and hence is defined to be whatever these methods do.

  2. Add a new reader control variable, *READ-EVAL*, whose default value is
  T.  If *READ-EVAL* is NIL, the #. reader macro signals an error.  If
  *READ-EVAL* is false and *PRINT-READABLY* is true, any PRINT-OBJECT
  method that would output a #. reader macro either outputs something
  different or signals an error of type PRINT-NOT-READABLE.

  3. Add a new macro:

  WITH-STANDARD-IO-SYNTAX &body body                             [Macro]
  
    Within the dynamic extent of <body>, all reader/printer control
    variables, including any implementation-defined ones not specified by
    Common Lisp, are bound to values that produce standard read/print
    behavior.  The values for Common Lisp specified variables are:

      *PACKAGE*                            The USER package
      *PRINT-ARRAY*                        T
      *PRINT-BASE*                         10
      *PRINT-CASE*                         :UPCASE
      *PRINT-CIRCLE*                       NIL
      *PRINT-ESCAPE*                       T
      *PRINT-GENSYM*                       T
      *PRINT-LENGTH*                       NIL
      *PRINT-LEVEL*                        NIL
      *PRINT-PRETTY*                       NIL
      *PRINT-RADIX*                        NIL
      *PRINT-READABLY*                     T
      *READ-BASE*                          10
      *READ-DEFAULT-FLOAT-FORMAT*          SINGLE-FLOAT
      *READ-EVAL*                          T
      *READ-SUPPRESS*                      NIL
      *READTABLE*                          The standard readtable

    The values returned by WITH-STANDARD-IO-SYNTAX are the values
    of the last body form, or NIL if there are no body forms.

  4. Add a new macro:

  PRINT-UNREADABLE-OBJECT (object stream &key type identity)      [Macro]
                           &body body

    Output a printed representation of <object> on <stream>, beginning with
    "#<" and ending with ">".  Everything output to <stream> by the <body>
    forms is enclosed in the angle brackets.  If :type is true, the body
    output is preceded by a brief description of the object's type and a
    space character.  If :identity is true, the body output is followed by
    a space character and a representation of the object's identity,
    typically a storage address.

    If *PRINT-READABLY* is true, PRINT-UNREADABLE-OBJECT signals an error
    of type PRINT-NOT-READABLE without printing anything.

    The <object>, <stream>, :type, and :identity arguments are all evaluated
    normally.  :type and :identity default to false.  It is valid to omit
    the <body> forms.  If :type and :identity are both true and there are no
    <body> forms, only one space character separates the type and the identity.

    The value returned by PRINT-UNREADABLE-OBJECT is NIL.

  5. Add a new condition type:

  PRINT-NOT-READABLE                                             [Type]

    Errors which occur during output while *PRINT-READABLY* is true, as a
    result of attempting to output a printed representation that cannot be
    read back, should inherit from this type.  This is a subtype of ERROR.
    The init keyword :OBJECT is supported to initialize the slot containing
    the object being printed, which can be accessed using
    PRINT-NOT-READABLE-OBJECT.

Examples:

  ;; Example #1: Reliable Write-Read

  (WITH-OPEN-FILE (FILE pathname :DIRECTION :OUTPUT)
    (WITH-STANDARD-IO-SYNTAX
      (PRINT DATA FILE)))

  ; ... Later, in another Lisp:

  (WITH-OPEN-FILE (FILE pathname :DIRECTION :INPUT)
    (WITH-STANDARD-IO-SYNTAX
      (SETQ DATA (READ FILE))))

  ;; Example #2: Use of PRINT-UNREADABLE-OBJECT
  ;; Note that in this example, the precise form of the output
  ;; is really implementation-dependent.

  (DEFMETHOD PRINT-OBJECT ((OBJ AIRPLANE) STREAM)
    (PRINT-UNREADABLE-OBJECT (OBJ STREAM :TYPE T :IDENTITY T)
      (PRINC (TAIL-NUMBER OBJ) STREAM)))

  (PRINT MY-AIRPLANE)
  #<Airplane NW0773 36000123135>        ;in Implementation A
  ;or
  #<FAA:AIRPLANE NW0773 17>             ;in Implementation B

Rationale:

  1. *PRINT-READABLY* is important so that errors involving data with no
  readable printed representation are detected when writing the file, not
  later on when the file is read.

  *PRINT-READABLY* is different from *PRINT-ESCAPE* because output printed
  with escapes only has to be generally recognizable by humans, whereas
  output printed readably has to be reliably recognizable by computers.

  2. Binding *READ-EVAL* to NIL is useful when reading data that came from
  an untrusted source, such as a network or a user-supplied data file, to
  prevent the #. reader macro from being exploited as a "Trojan horse" to
  cause arbitrary forms to be evaluated.

  3. Providing the WITH-STANDARD-IO-SYNTAX macro to bind all the variables,
  instead of using LET and explicit bindings of the existing variables,
  ensures that nothing is overlooked and avoids problems with
  implementation-defined reader/printer control variables.

  If the user wishes to use a non-standard value for some variable, such as
  *PACKAGE* or *READ-EVAL*, it can be bound by LET inside the body of
  WITH-STANDARD-IO-SYNTAX.  Similarly, if the user dislikes the somewhat
  arbitrary choices of values for *PRINT-CIRCLE* and *PRINT-PRETTY*, they
  can be bound to the preferred values inside the body.

  4. PRINT-UNREADABLE-OBJECT allows user-written PRINT-OBEJCT methods to
  adhere to implementation-specific style without requiring users to write
  implementation-dependent code.

  5. Defining a specific condition type associated with *PRINT-READABLY*
  makes it possible for programs to handle the condition and recognize
  the offending object.

Current practice:

  Symbolics Genera has had these features for many years, except with
  different names.  For instance, WITH-STANDARD-IO-SYNTAX is named
  WITH-STANDARD-IO-ENVIRONMENT and binds *PACKAGE* to a non-standard
  package.  The proposed new names are better than the Genera names.

  Genera's WITH-STANDARD-IO-ENVIRONMENT also disables #., to prevent trojan
  horses, since #. could evaluate an arbitrary form.  This is particularly
  important for network protocols.  WITH-STANDARD-IO-SYNTAX does not bind
  *READ-EVAL* to NIL, because that would prevent using #. in the printer
  for common datatypes, which is current practice in some implementations
  for printing PATHNAMEs or RANDOM-STATEs.

  In Genera, PRINT-UNREADABLE-OBJECT is called SYS:PRINTING-RANDOM-OBJECT
  and takes slightly different arguments. In PCL, PRINT-UNREADABLE-OBJECT
  is called PCL:PRINTING-RANDOM-THING.

Cost to Implementors:

  Very small, these features are all easy to add.  If #. is output by any
  system-supplied print methods, they might want to invent a different
  syntax, however that is not required by this proposal.

Cost to Users:

  None if they don't use the feature.  Otherwise just the cost of
  supporting *PRINT-READABLY* or using PRINT-UNREADABLE-OBJECT in their
  PRINT-OBJECT methods.

Cost of non-adoption:

  There will be no reliable, standard way to write data into a file.

Performance impact:

  Negligible.  Entering WRITE may be slightly slower since there is
  one more keyword argument to parse and one more special variable
  to bind before calling PRINT-OBJECT.

Benefits:

  Data can be written into files reliably without resorting to
  implementation-specific programming.

Esthetics:

  Mildly improved.

Discussion:

  Pitman and Moon support this proposal.

∂23-Jun-89  1050	X3J13-mailer 	Issue: MAP-INTO (version 3)    
Received: from STONY-BROOK.SCRC.Symbolics.COM by SAIL.Stanford.EDU with TCP; 23 Jun 89  10:50:30 PDT
Received: from KENNETH-WILLIAMS.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via INTERNET with SMTP id 616033; 23 Jun 89 13:52:24 EDT
Date: Fri, 23 Jun 89 13:50 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Issue: MAP-INTO (version 3)
To: X3J13@sail.stanford.edu
Message-ID: <19890623175044.4.MOON@KENNETH-WILLIAMS.SCRC.Symbolics.COM>

This is a new issue.  It arose from an investigation of features
that are plausibly needed but missing from draft ANSI Common Lisp.
This issue seems sufficiently simple and noncontroversial that
I would like to see it on the agenda for the June X3J13 meeting.

This version has been revised based on BarMar's suggestions: It can
be called without any argument sequences; if the result sequence is
a vector with a fill-pointer, the fill-pointer's current value is
ignored, and the fill-pointer is set to the number of results produced.

Issue:          MAP-INTO
References:     none
Related issues: BIT-ARRAY-FUNCTIONS
Category:       ADDITION
Edit history:   23-May-89, version 1 by Moon
                19-Jun-89, version 2 by Moon (fix arglist)
                23-Jun-89, version 3 by Moon (include BarMar's suggestions)

Problem description:

  The function MAP is very useful but can be a source of inefficiency
  because it conses the result.  Sometimes the user has storage
  already allocated in which the result could be stored.

Proposal (MAP-INTO:ADD-FUNCTION):

  Add the following function:

    MAP-INTO result-sequence function &rest sequences            [Function]

    Destructively modifies the result-sequence to contain the results of
    applying function to each element in the argument sequences in turn.
    Returns result-sequence.

    The arguments result-sequence and each element of sequences can each be
    either a list or a vector (one-dimensional array).  Note that NIL is
    considered to be a sequence, of length zero.  If result-sequence and
    each element of sequences are not all the same length, the iteration
    terminates when the shortest sequence is exhausted.  If result-sequence
    is a vector with a fill-pointer, the fill-pointer is ignored when
    deciding how many iterations to perform, and afterwards the
    fill-pointer is set to the number of times function was applied.

    If result-sequence is longer than the shortest element of sequences,
    extra elements at the end of result-sequence are left unchanged.

    MAP-INTO differs from MAP in that it modifies an existing sequence
    rather than creating a new one.  In addition, MAP-INTO can be called
    with only two arguments, while MAP requires at least three arguments.
    If result-sequence is NIL, MAP-INTO immediately returns NIL, since
    NIL is a sequence of length zero.

    If BIT-ARRAY-FUNCTIONS:NO-NEW-FUNCTIONS passes, then MAP-INTO will
    allow result-sequence and each element of sequences to be mappables
    all of the same rank.

    The function must take at least as many arguments as there are
    sequences provided.

    If function has side effects, it can count on being called first on all
    of the elements with index 0, then on all of those numbered 1, and so
    on.

Examples:

  (map-into x #'+ x y)
  (map-into q #'cons keys vals)
  (map-into syms #'gensym)

Rationale:

  MAP-INTO is a simple way to express reuse of storage that is
  stylistically consistent with the rest of Common Lisp.

Current practice:

  Symbolics Genera 7.2 implements the proposal.

Cost to Implementors:

  Small.

Cost to Users:

  None.

Cost of non-adoption:

  Small.

Performance impact:

  None.

Benefits:

  More expressive language.

Esthetics:

  User programs won't have to write the above examples as

   (loop for xx on x and yy in y do
      (setf (car xx) (+ (car xx) yy)))

  or something else about equally horrible.

Discussion:

  None.

∂23-Jun-89  1051	X3J13-mailer 	Issue: PATHNAME-LOGICAL (version 4) 
Received: from STONY-BROOK.SCRC.Symbolics.COM by SAIL.Stanford.EDU with TCP; 23 Jun 89  10:51:11 PDT
Received: from KENNETH-WILLIAMS.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via INTERNET with SMTP id 616034; 23 Jun 89 13:53:02 EDT
Date: Fri, 23 Jun 89 13:51 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Issue: PATHNAME-LOGICAL (version 4)
To: X3J13@sail.stanford.edu
Message-ID: <19890623175120.5.MOON@KENNETH-WILLIAMS.SCRC.Symbolics.COM>

This is an old issue but it has not been written up before.  I'm sorry this
is coming out so late, but it's been quite a struggle to cast it into clear
and easily understood form.  It is rather a long proposal in order to be
very clear about exactly what it's proposing, and I apologize for the
length.

This version has been amended and simplified based on last-minute
discussion: Support for back-translation has been removed.
TRANSLATE-LOGICAL-PATHNAME now returns only value, but has added ability
for implementations to add keyword arguments and extra return values.
I also made a minor clarification under LOGICAL-PATHNAME-TRANSLATIONS.
The LOGICAL-DIRECTORY example has been removed, as it is no longer
possible for a user to implement that functionality.


Issue:          PATHNAME-LOGICAL
Forum:          Cleanup
References:     Pathnames (pp410-413)
                OPEN (p.418), WITH-OPEN-FILE (p.422), RENAME-FILE (p.423),
                DELETE-FILE (p.424), PROBE-FILE (p.424),
                FILE-WRITE-DATE (p.424), FILE-AUTHOR (p.424), LOAD (p.426),
                COMPILE-FILE (p.439), DIRECTORY (p.427), PATHNAME (p.413),
                TRUENAME (p.413), MERGE-PATHNAMES (p.415), 
                MAKE-PATHNAME (p.416), and PARSE-NAMESTRING (p.414).
Related issues: PATHNAME-CANONICAL-TYPE, PATHNAME-COMPONENT-VALUES, 
                PATHNAME-SUBDIRECTORY-LIST, and PATHNAME-WILD
Category:       ADDITION
Edit history:   Version 1, 11-May-89, by Moon
                Version 2, 18-May-89, by Moon
                Version 3, 21-Jun-89, by Moon (revise based on discussion
                        in the cleanup committee)
                Version 4, 23-Jun-89, by Moon (remove backtranslation)

Problem description:

  Pathname values are not portable, but they are sometimes part of a
  program, for example the names of files containing the program and the
  data used by the program.  Moving large programs between sites would
  be easier if pathname values did not have to be translated.

  Pathname values are nonportable because not all Common Lisp
  implementations use the same operating system and file name syntax varies
  widely among operating systems.  In addition, corresponding files at two
  different sites may have different names even when the operating system
  is the same; for example, they may be on different directories or
  different devices.

  The issue of portable pathname values is separate from the issues of
  portable pathname operations.  See the related issues listed above.
  For inter-issue interactions, see the discussion section below.

  Note that issue PATHNAME-LOGICAL fundamentally depends on issue
  PATHNAME-WILD.  If PATHNAME-WILD:NEW-FUNCTIONS does not pass,
  PATHNAME-LOGICAL cannot pass.

Proposal (PATHNAME-LOGICAL:ADD):

  1. Define a "logical" file system that looks the same at every site.
  This file system is implemented by translating each logical pathname into
  a physical pathname on a real file system.  The logical pathnames are the
  same at all sites, but the translations are different at each site, thus
  the physical pathnames can be different at each site.

  2a. The syntax of a logical pathname namestring is as follows:

  [ host ":" ] [ ";" ] { directory ";" }* [ name ] [ "." type [ "." version ]]

  2b. Terminology:

  A <word> consists of one or more uppercase letters, digits, and hyphens.

  A <wildcard word> consists of one or more asterisks, uppercase letters,
  digits, and hyphens, including at least one asterisk, with no two
  asterisks adjacent.  Each asterisk matches a sequence of zero or more
  characters.  The <wildcard word> "*" parses into :WILD, the others parse
  into strings.

  In <words> and <wildcard words> lowercase letters are translated to
  uppercase.  The consequences of using other characters are unspecified.

  2c. Logical pathname components:

  The host is a <word> that has been defined as a logical pathname host by
  using SETF of LOGICAL-PATHNAME-TRANSLATIONS.

  There is no device, so the device component of a logical pathname is
  always :UNSPECIFIC.  No other component can be :UNSPECIFIC.

  Each directory is a <word>, a <wildcard word>, or "**" (:WILD-INFERIORS).
  If a semicolon precedes the directories, the directory component is
  relative, otherwise it is absolute.

  The name is a <word> or a <wildcard word>.

  The type is a <word> or a <wildcard word>.

  The version is a positive decimal integer or "NEWEST" (:NEWEST) or "*"
  (:WILD).  The letters in "NEWEST" can be in either alphabetic case.

  The consequences of using any value not specified here as a logical
  pathname component are unspecified.

  The null string "" is not a valid value for any component of a logical
  pathname, since "" is not a <word> and not a <wildcard word>.

  3. Parsing of logical pathname namestrings into logical pathnames
  operates as follows:

  3a. Logical pathname namestrings are recognized by the LOGICAL-PATHNAME
  and TRANSLATE-LOGICAL-PATHNAME functions.  In this case the host portion
  of the logical pathname namestring and its following colon are required.

  3b. The PARSE-NAMESTRING function recognizes a logical pathname
  namestring when the host argument is logical or the defaults argument is
  a logical pathname.  In this case the host portion of the logical
  pathname namestring and its following colon are optional.  If the host
  portion of the namestring and the host argument are both present and do
  not match, an error is signalled.

  The host argument is logical if it is supplied and came from
  PATHNAME-HOST of a logical pathname.  Whether a host argument is logical
  if it is a string equal to a logical pathname host name is
  implementation-defined.

  3c. The MERGE-PATHNAMES function recognizes a logical pathname namestring
  when the defaults argument is a logical pathname.  In this case the host
  portion of the logical pathname namestring and its following colon are
  optional.

  3d. Whether the other functions that coerce strings to pathnames
  (PATHNAME, TRUENAME, PARSE-NAMESTRING in other circumstances than those
  described in point 3b, MERGE-PATHNAMES in other circumstances than those
  described in point 3c, the :DEFAULTS argument to MAKE-PATHNAME,
  PATHNAME-HOST, PATHNAME-DEVICE, PATHNAME-DIRECTORY, PATHNAME-NAME,
  PATHNAME-TYPE, PATHNAME-VERSION, NAMESTRING, FILE-NAMESTRING,
  DIRECTORY-NAMESTRING, HOST-NAMESTRING, ENOUGH-NAMESTRING, OPEN,
  WITH-OPEN-FILE, RENAME-FILE, DELETE-FILE, PROBE-FILE, FILE-WRITE-DATE,
  FILE-AUTHOR, LOAD, DIRECTORY, COMPILE-FILE, ED, DRIBBLE, WILD-PATHNAME-P,
  PATHNAME-MATCH-P, TRANSLATE-PATHNAME, and COMPILE-FILE-PATHNAME)
  recognize logical pathname namestrings is implementation defined.

  4. Some real file systems do not have versions.  Logical pathname
  translation to such a file system ignores the version.  This implies that
  a program cannot rely on being able to store more than one version of a
  file named by a logical pathname.

  5. The type of a logical pathname for a Common Lisp source file is "LISP".
  This should be translated into whatever type is appropriate in a physical
  pathname.

  6. The logical pathname host name "SYS" is reserved for the implementation.
  The existence and meaning of SYS: logical pathnames is
  implementation-defined.

  7. File manipulation functions operate with logical pathnames as follows:

  7a. The functions OPEN (and WITH-OPEN-FILE), RENAME-FILE, DELETE-FILE,
  PROBE-FILE, FILE-WRITE-DATE, FILE-AUTHOR, LOAD, DIRECTORY, COMPILE-FILE,
  ED, DRIBBLE, COMPILE-FILE-PATHNAME, and TRUENAME accept logical pathnames
  and translate them into physical pathnames, as if by calling the
  TRANSLATE-LOGICAL-PATHNAME function.

  7b. PATHNAME of a stream created by OPEN (or WITH-OPEN-FILE) of a logical
  pathname is a logical pathname.

  7c. TRUENAME, PROBE-FILE, and DIRECTORY never return logical pathnames.

  7d. RENAME-FILE with a logical pathname as the second argument returns a
  logical pathname as the first value.

  7e. MERGE-PATHNAMES returns a logical pathname if and only if its first
  argument is a logical pathname or its first argument does not specify a
  host and the default is a logical pathname.

  7f. MAKE-PATHNAME returns a logical pathname if and only if the host is
  logical.  If the :host argument to MAKE-PATHNAME is supplied, the host is
  logical if it came from PATHNAME-HOST of a logical pathname.  Whether a
  :host argument is logical if it is a string equal to a logical pathname
  host name is implementation-defined.

  7g. PARSE-NAMESTRING returns a logical pathname according to points 3b
  and 3d.

  Add these defined names to Common Lisp in support of logical pathnames:

  8. LOGICAL-PATHNAME                                            [Class]

    LOGICAL-PATHNAME is a subclass of PATHNAME.

  9. LOGICAL-PATHNAME pathname                                   [Function]

    Converts the argument to a logical pathname and returns it.  The
    argument can be a logical pathname, a logical pathname namestring
    containing a host component, or a stream for which the PATHNAME
    function returns a logical pathname.  For any other argument,
    LOGICAL-PATHNAME signals an error of type TYPE-ERROR.

  10. TRANSLATE-LOGICAL-PATHNAME pathname &key                   [Function]

    Translates a logical pathname to the corresponding physical pathname.
    The pathname argument is first coerced to a pathname.  If it is not a
    pathname, string, or file stream an error of type TYPE-ERROR is
    signalled.

    If the coerced argument is a physical pathname, it is returned.

    If the coerced argument is a logical pathname, the first matching
    translation (according to PATHNAME-MATCH-P) of the logical pathname
    host is applied, as if by calling TRANSLATE-PATHNAME.  If the result is
    a logical pathname, this process is repeated.  When the result is
    finally a physical pathname, it is returned.

    If no translation matches, an error of type FILE-ERROR is signalled.

    TRANSLATE-LOGICAL-PATHNAME might perform additional translations,
    typically to provide translation of file types to local naming
    conventions, to accomodate physical file systems with limited length
    names, or to deal with special character requirements such as
    translating hyphens to underscores or uppercase letters to lowercase.
    Any such additional translations are implementation defined.  Some
    implementations do no additional translations.

    There are no specified keyword arguments for
    TRANSLATE-LOGICAL-PATHNAME, but implementations are permitted to extend
    it by adding keyword arguments.  There is one specified return value
    from TRANSLATE-LOGICAL-PATHNAME; implementations are permitted to
    extend it by returning additional values.

  11. LOGICAL-PATHNAME-TRANSLATIONS host                         [Function]

    If <host> is not the host component of a logical pathname and not a
    string that has been defined as a logical pathname host name by SETF of
    LOGICAL-PATHNAME-TRANSLATIONS, signals an error of type TYPE-ERROR.
    Otherwise returns the host's list of translations.  Each translation is
    a list of at least two elements: from-wildcard and to-wildcard.  Any
    additional elements are implementation defined.  From-wildcard is a
    logical pathname whose host is <host>.  To-wildcard is a pathname.
    Translations are searched in the order listed, so more specific
    from-wildcards must precede more general ones.

    (SETF (LOGICAL-PATHNAME-TRANSLATIONS host) translations) sets a logical
    pathname host's list of translations.  If <host> is a string that has
    not been previously used as logical pathname host, a new logical
    pathname host is defined, otherwise an existing host's translations are
    replaced.  Logical pathname host names are compared with STRING-EQUAL.

    When setting the translations list, each from-wildcard can be a logical
    pathname whose host is <host> or a logical pathname namestring
    parseable by (PARSE-NAMESTRING string <<host>>), where <<host>>
    represents the appropriate object as defined in point 3b.  Each
    to-wildcard can be anything coercible to a pathname by
    (PATHNAME to-wildcard).  If to-wildcard coerces to a logical pathname,
    TRANSLATE-LOGICAL-PATHNAME will perform repeated translation steps when
    it uses it.

    Implementations can define additional functions that operate on
    logical pathname hosts, for example to specify additional translation
    rules or options.

  12. LOAD-LOGICAL-PATHNAME-TRANSLATIONS host                    [Function]

    If a logical pathname host named <host> (a string) is already defined,
    return NIL.  Otherwise, search for a logical pathname host definition
    in an implementation defined manner.  If none is found, signal an
    error.  If a definition is found, install it and return T.

    The search used by LOAD-LOGICAL-PATHNAME-TRANSLATIONS should be
    documented, as logical pathname definitions will be created by users,
    not only by Lisp implementors.  A typical search technique is to
    look in a certain directory for a file whose name is derived from
    the host name in an implementation-defined fashion.

  13. COMPILE-FILE-PATHNAME pathname &key :output-file           [Function]

    Returns the pathname that COMPILE-FILE would write into, if given the
    same arguments.  If the pathname argument is a logical pathname and the
    :output-file argument is unspecified, the result is a logical pathname.
    If an implementation supports additional keyword arguments to
    COMPILE-FILE, COMPILE-FILE-PATHNAME must accept the same arguments.

Examples:

  ;A very simple example of setting up a logical pathname host.  No
  ;translations are necessary to get around file system restrictions, so
  ;all that is necessary is to specify the root of the physical directory
  ;tree that contains the logical file system.
  ;The namestring syntax on the right-hand side is implementation-specific.
  (setf (logical-pathname-translations "foo")
        '(("**;*.*.*"              "MY-LISPM:>library>foo>**>")))

  ;Sample use of that logical pathname.  All return values
  ;are of course implementation-specific.
  (translate-logical-pathname "foo:bar;baz;mum.quux.3")
  => MY-LISPM:>library>foo>bar>baz>mum.quux.3

  ;A more complex example, dividing the files among two file servers
  ;and several different directories.  This Unix doesn't support
  ;:WILD-INFERIORS in the directory, so each directory level must
  ;be translated individually.  No file name or type translations
  ;are required except for .MAIL to .MBX.
  ;The namestring syntax on the right-hand side is implementation-specific.
  (setf (logical-pathname-translations "prog")
        '(("RELEASED;*.*.*"        "MY-UNIX:/sys/bin/my-prog/")
          ("RELEASED;*;*.*.*"      "MY-UNIX:/sys/bin/my-prog/*/")
          ("EXPERIMENTAL;*.*.*"    "MY-UNIX:/usr/Joe/development/prog/")
          ("EXPERIMENTAL;DOCUMENTATION;*.*.*"
                                   "MY-VAX:SYS$DISK:[JOE.DOC]")
          ("EXPERIMENTAL;*;*.*.*"  "MY-UNIX:/usr/Joe/development/prog/*/")
          ("MAIL;**;*.MAIL"        "MY-VAX:SYS$DISK:[JOE.MAIL.PROG...]*.MBX")))

  ;Sample use of that logical pathname.  All return values
  ;are of course implementation-specific.
  (translate-logical-pathname "prog:mail;save;ideas.mail.3")
  => MY-VAX:SYS$DISK:[JOE.MAIL.PROG.SAVE]IDEAS.MBX.3

  ;Example translations for a program that uses three files main.lisp,
  ;auxiliary.lisp, and documentation.lisp.  These translations might be
  ;supplied by a software supplier as examples.

  ;For Unix with long file names
  (setf (logical-pathname-translations "prog")
        '(("CODE;*.*.*"             "/lib/prog/")))

  ;Sample use of that logical pathname.  All return values
  ;are of course implementation-specific.
  (translate-logical-pathname "prog:code;documentation.lisp")
  => /lib/prog/documentation.lisp

  ;For Unix with 14-character file names, using .lisp as the type
  (setf (logical-pathname-translations "prog")
        '(("CODE;DOCUMENTATION.*.*" "/lib/prog/docum.*")
          ("CODE;*.*.*"             "/lib/prog/")))

  ;Sample use of that logical pathname.  All return values
  ;are of course implementation-specific.
  (translate-logical-pathname "prog:code;documentation.lisp")
  => /lib/prog/docum.lisp

  ;For Unix with 14-character file names, using .l as the type
  ;The second translation shortens the compiled file type to .b
  (setf (logical-pathname-translations "prog")
        `(("**;*.LISP.*"            ,(logical-pathname "PROG:**;*.L.*"))
          (,(compile-file-pathname (logical-pathname "PROG:**;*.LISP.*"))
                                    ,(logical-pathname "PROG:**;*.B.*"))
          ("CODE;DOCUMENTATION.*.*" "/lib/prog/documentatio.*")
          ("CODE;*.*.*"             "/lib/prog/")))

  ;Sample use of that logical pathname.  All return values
  ;are of course implementation-specific.
  (translate-logical-pathname "prog:code;documentation.lisp")
  => /lib/prog/documentatio.l

  ;For a Cray with 6 character names and no directories, types, or versions.
  (setf (logical-pathname-translations "prog")
        (let ((l '(("MAIN" "PGMN")
                   ("AUXILIARY" "PGAUX")
                   ("DOCUMENTATION" "PGDOC")))
              (logpath (logical-pathname "prog:code;"))
              (phypath (pathname "XXX")))
          (append
            ;; Translations for source files
            (mapcar #'(lambda (x)
                        (let ((log (first x))
                              (phy (second x)))
                          (list (make-pathname :name log
                                               :type "LISP"
                                               :version :wild
                                               :defaults logpath)
                                (make-pathname :name phy
                                               :defaults phypath))))
                    l)
            ;; Translations for compiled files
            (mapcar #'(lambda (x)
                        (let* ((log (first x))
                               (phy (second x))
                               (com (compile-file-pathname
                                      (make-pathname :name log
                                                     :type "LISP"
                                                     :version :wild
                                                     :defaults logpath))))
                          (setq phy (concatenate 'string phy "B"))
                          (list com
                                (make-pathname :name phy
                                               :defaults phypath))))
                    l))))

  ;Sample use of that logical pathname.  All return values
  ;are of course implementation-specific.
  (translate-logical-pathname "prog:code;documentation.lisp")
  => PGDOC

Rationale:

  1. Large programs can be moved between sites without changing any
  pathnames, provided all pathnames used are logical.  A portable system
  construction tool can be created that operates on programs defined as
  sets of files named by logical pathnames.

  2. Logical pathname syntax was chosen to be easily translated into most
  popular file systems, while still being powerful enough for storing large
  programs.  Although they have hierarchical directories, extended wildcard
  matching, versions, and no limit on the length of names, they can be
  mapped onto a less capable real file file system by translating each
  directory that is used into a flat directory name, doing wildcards in
  Lisp rather than in the file system, treating all versions as :newest,
  and/or using translations to shorten long names.

  Logical pathname words are restricted to non-case-sensitive letters,
  digits, and hyphens to avoid creating problems with real file systems
  that support limited character sets for file naming.  Other characters
  could have been mapped onto such file systems through translations, but
  that didn't seem worth the trouble.  Logical pathnames have to be
  non-case-sensitive or it would be very difficult to map them onto a
  non-case-sensitive file system.

  Features such as :UP and :BACK relative directories and a namestring
  syntax for the root directory were not felt to be necessary in logical
  pathnames.  They could be added later if a need emerges.

  It is not a goal of logical pathnames to be able to represent all
  possible file names.  Their goal is rather to represent just enough file
  names to be useful for storing software.  Real pathnames, in contrast,
  need to provide a uniform interface to all possible file names, including
  names and naming conventions that are not under the control of Common
  Lisp.

  The choice of logical pathname syntax, using colon, semicolon, and
  period, was guided by the goals of being visually distinct from real file
  systems and minimizing the use of special characters.

  The consequences of using any value not specified here as a logical
  pathname component are unspecified, for the benefit of the Explorer.

  3. The LOGICAL-PATHNAME function is separate from the PATHNAME function
  so that the syntax of logical pathname namestrings does not constrain the
  syntax of physical pathname namestrings in any way.  Logical pathname
  syntax must be defined by Common Lisp so that logical pathnames can be
  conveniently exchanged between implementations, but physical pathname
  syntax is dictated by forces outside our control.

  3b,c. Allowing PARSE-NAMESTRING and MERGE-PATHNAMES to recognize logical
  pathname namestrings in these situations provides for natural operations
  on logical pathnames.  Frequently a string containing just a name, or a
  name and a type, will be recognized as a logical pathname by merging it
  against a default containing a logical pathname host and directory.

  3d. Recognition of logical pathname namestrings by PATHNAME and related
  functions is left up to each implementation because some implementations
  definitely require this, other implementations don't want to do this, and
  nobody wants to change.  In any case, Common Lisp historically has avoided
  saying anything about the syntax of the strings accepted by the PATHNAME
  function, and point 3d preserves that position.

  3b,7f. Leaving it implementation defined whether a string, used as the
  host argument to PARSE-NAMESTRING or the :host argument to MAKE-PATHNAME,
  can be recognized as logical pathname host name is for the same reason as
  point 3d.  It allows each implementation to decide whether there is one
  namespace or two.  The correct way to write this is:

    (MAKE-PATHNAME :HOST (PATHNAME-HOST (LOGICAL-PATHNAME "hostname:"))
                   ...)

  4. Logical pathname versions could have been supported on real file
  systems that do not have versions by defining a kind of translation to
  encode the version number in the name.  However, the typical use of
  versions is such that on a file system without versions, people would
  rather just store one version of a file, and not preserve the version
  information by encoding it somehow in the name.  This is different from
  the typical use of types or directories, where the files with different
  values in those components are truly distinct and everything would break
  if you only kept one file.

  5,13. The COMPILE-FILE-PATHNAME function and the specification of "LISP"
  as the type of a logical pathname for a Common Lisp source file together
  provide enough information about compilation for a portable system
  construction tool that uses logical pathnames to work.  Suppose you want
  to call COMPILE-FILE only if the source file is newer than the compiled
  file.  To do that, you have to have a way to know the name of the
  compiled file without actually calling COMPILE-FILE.
  No standard file type for compiler output is proposed, because in some
  implementations the compiler produces one of several file types,
  depending on a variety of implementation-dependent circumstances.
  COMPILE-FILE-PATHNAME provides access to the "default[ing] in a manner
  appropriate to the implementation's file system conventions" mentioned in
  the CLtL documentation of COMPILE-FILE.

  6. The use of the logical pathname host name "SYS" for the implementation
  is current practice.  Standardizing on this name helps users choose
  logical pathname host names that avoid conflicting with
  implementation-defined names.

  7. Accepting logical pathnames for file access is a natural extension
  of the file access functions and makes it easier to program using only
  logical pathnames in situations where that is appropriate.

  8. The LOGICAL-PATHNAME class exists so that methods can distinguish
  logical pathnames from regular pathnames.

  9. See point 3 above.

  10. TRANSLATE-LOGICAL-PATHNAME is the heart of the logical pathname
  feature.  Allowing TRANSLATE-LOGICAL-PATHNAME on a physical pathname,
  simply returning the argument, makes some programs easier to write.
  Additional implementation defined translations make it possible for
  implementations with unusual file systems to offer some help to the user
  in setting up the translations for a logical pathname host, by handling
  some of the work automatically.  Logical pathnames that translate to
  other logical pathnames are a feature that several people have requested.

  11. SETF of LOGICAL-PATHNAME-TRANSLATIONS is a simple way for a user to
  define a new logical pathname host.  Using SETF makes it possible to add
  to or modify the translations of an existing logical pathname host.

  It is always up to the person who writes the translation rules for a
  particular logical pathname host to a particular physical file system to
  make sure that the logical pathnames that are actually going to be used
  translate to valid pathnames for the particular file system, and that
  no two logical pathnames that are supposed to be distinct translate to
  the same physical pathname.

  12. Loading of logical pathname translations from a site-dependent file
  allows software to be distributed using logical pathnames.  The assumed
  model of software distribution is a division of labor between the
  supplier of the software and the user installing it.  The supplier
  chooses logical pathnames to name all the files used or created by the
  software, and supplies examples of logical pathname translations for a
  few popular file systems.  Each example uses an assumed directory and/or
  device name, assumes local file naming conventions, and provides
  translations that will translate all the logical pathnames used or
  generated by the particular software into valid physical pathnames.
  For a powerful file system these translations can be quite simple.  For
  a more restricted file system, it may be necessary to list an explicit
  translation for every logical pathname used, for example when dealing
  with restrictions on the maximum length of a file name.

  The user installing the software decides on which device and/or directory
  to store the files and edits the example logical pathname translations
  accordingly.  If necessary, the user also adjusts the translations for
  local file naming conventions and any other special aspects of the user's
  local file system policy and local Common Lisp implementation.  For
  example, the files might be divided among several file server hosts to
  share the load.  The process of defining site-customized logical pathname
  translations is quite easy for a user of a popular file system for which
  the software supplier has provided an example.  A user of a more unusual
  file system might have to take more time; the supplier can help by
  providing a list of all the logical pathnames used or generated by the
  software.

  Once the user has created a suitable SETF of LOGICAL-PATHNAME-TRANSLATIONS
  form, he can evaluate that form and then load and run the software.  It
  may be necessary to use the translations again, or on another workstation
  at the same site, so it is best to save the SETF form in the standard
  place where it can be found later by LOAD-LOGICAL-PATHNAME-TRANSLATIONS.
  Often a software supplier will include a program for restoring software
  from the distribution medium to the file system, and a program for loading
  the software from the file system into a Common Lisp, and these programs
  will start by calling LOAD-LOGICAL-PATHNAME-TRANSLATIONS to make sure that
  the logical pathname host is defined.

  Note that the SETF of LOGICAL-PATHNAME-TRANSLATIONS form isn't part of
  the program, it's separate.  It's written by the user, not by the
  software supplier.  That separation, and a uniform convention for how to
  do the separation, are the key aspects of logical pathnames.  For small
  programs involving only a handful of files, it doesn't matter much.  The
  real benefits come with large programs with hundreds or thousands of
  files and more complicated situations such as program-generated file
  names or porting a program developed on a system with long file names
  onto a system with a very restrictive limit on the length of file names.

Current practice:

  Symbolics Genera has had a similar facility for many years.  It is used
  extensively for software distribution by Symbolics and its customers.
  The Genera facility uses the same logical pathname syntax but different
  function names, and is somewhat more complicated.  The extra complexity
  is not necessary in the Common Lisp standard.

  The T.I. Explorer also has a comparable logical pathname facility,
  although the translation mechanism is unfortunately less general than
  proposed here.  The namestring syntax used is slightly different:
  
    host ":" [{directory "."}* directory ";"] [name] ["." type] ["#" version]
  
  The newest version is indicated by ">" instead of "newest".

  Macintosh Allegro Common Lisp) has a logical pathname feature which is
  somewhat simpler but aimed at solving the same problems.  It has logical
  directory names, to simplify access to sets of files in differently named
  directories (an especially severe problem on micros where everybody just
  has to have a different pet name for their hard disk).  This isn't really
  the same as simplifying access to different file systems, although of
  course solving the latter automatically solves the former.  In general,
  access to different file systems requires translating names and types,
  not just translating directories.

  Symbolics Genera offers a function for translating from a physical
  pathname back to a logical pathname.  There are a number of problems with
  this, and so it has not been proposed here.  An earlier version specified
  TRANSLATE-LOGICAL-PATHNAME to return enough information to allow the user
  program to perform the backtranslation itself, but that hsd problems
  so it was removed.

  The Genera equivalent of LOAD-LOGICAL-PATHNAME-TRANSLATIONS looks for
  a file named SYS:SITE;hostname.TRANSLATIONS.

  Current practice in Genera, Explorer, and Macintosh has one namespace for
  both logical and physical namestrings.  This proposal allows an
  implementation to choose to have one namespace or to have two separate
  namespaces for namestrings.

Cost to Implementors:

  This is a fairly complex facility, but its performance is unimportant
  so a straightforward implementation should suffice.  Most of the
  complexity comes in dealing with unusual file systems, such as ones
  that don't allow long file names.

Cost to Users:

  None.

Cost of non-adoption:

  Portable software construction and distribution will have to rely on
  implementation-dependent kludges.  Lisp software will continue to be
  difficult to install.

Performance impact:

  None.

Benefits:

  Avoid cost of non-adoption.

Esthetics:

  Improved portability of large programs.

Discussion:

  Issue PATHNAME-LOGICAL fundamentally depends on issue PATHNAME-WILD.  If
  PATHNAME-WILD:NEW-FUNCTIONS does not pass, PATHNAME-LOGICAL cannot pass.

  If PATHNAME-CANONICAL-TYPE:NEW-CONCEPT passes, it will affect the
  behavior of the function TRANSLATE-PATHNAME and therefore the behavior of
  the function TRANSLATE-LOGICAL-PATHNAME.  When a logical pathname
  translation has from-wildcard and to-wildcard type components that are
  :WILD or omitted, translation of the type will be guided by canonical
  types.  If PATHNAME-CANONICAL-TYPE:NEW-CONCEPT fails to pass, it will
  either have to be done behind the scenes by TRANSLATE-PATHNAME or users
  will have to write more verbose translations that individually specify
  the handling of each file type (as shown in some of the examples here).

∂23-Jun-89  1052	X3J13-mailer 	Issue: PATHNAME-WILD (version 7)    
Received: from STONY-BROOK.SCRC.Symbolics.COM by SAIL.Stanford.EDU with TCP; 23 Jun 89  10:51:51 PDT
Received: from KENNETH-WILLIAMS.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via INTERNET with SMTP id 616035; 23 Jun 89 13:53:42 EDT
Date: Fri, 23 Jun 89 13:52 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Issue: PATHNAME-WILD (version 7)
To: X3J13@sail.stanford.edu
Message-ID: <19890623175202.6.MOON@KENNETH-WILLIAMS.SCRC.Symbolics.COM>

This issue is on the agenda for the June X3J13 meeting.  KMP and I
have prepared a revised writeup which we think is ready for release.

This version has been updated based on last minute discussion:
Remove reversible argument from TRANSLATE-PATHNAME, add ability for
implementations to add keyword arguments and extra return values.

Issue:        PATHNAME-WILD
Forum:        Cleanup
References:   Pathnames (pp410-413)
Related issues: PATHNAME-COMPONENT-VALUE, PATHNAME-LOGICAL
Category:     ADDITION
Edit history: 21-Jul-88, Version 1 by Pitman
              06-Oct-88, Version 2 by Pitman
               9-May-89, Version 3 by Moon (small fixes)
              10-May-89, Version 4 by Moon (add two more functions)
              13-May-89, Version 5 by Moon (minor cleanups, add clarification)
              19-Jun-89, Version 6 by Moon (revise based on extensive
                        discussion in the cleanup subcommittee; rewrite
                        the description of TRANSLATE-PATHNAME so it is
                        possible to understand it)
              23-Jun-89, Version 7 by Moon (simplify TRANSLATE-PATHNAME
                        based on last minute discussion of logical pathnames)

Problem Description:

  Some file systems provide more complex conventions for wildcards than
  simple component-wise wildcards (:WILD). For example,

  "F*O" might mean:
    - a normal three character name
    - a three-character name, with the middle char wild
    - at least a two-character name, with the middle 0 or more chars wild
    - a wild match spanning multiple directories

  ">foo>*>bar" might imply:
    - the middle directory is named "*"
    - the middle directory is :WILD
    - there may be zero or more :WILD middle directories
    - the middle directory name matches any one-letter name

  ">foo>**>bar" might mean
    - the middle directory is named "**"
    - the middle directory is :WILD
    - there may be zero or more :WILD middle directories
    - the middle directory name matches any two-letter name

  Some file systems support even more complex wildcards, for example
  regular expressions.

  The CL pathname model does not specify a way to represent complex
  wildcards, which means, for example, that (MAKE-PATHNAME :NAME "F*O")
  cannot be recognized by portable code as containing a wildcard.

  Common Lisp provides only the first of these four common operations
  on wildcard pathnames:
  (1) Enumerate the set of existing files that match the pathname;
  this is provided by the DIRECTORY function.
  (2) Test whether a pathname contains wildcards.
  (3) Test whether a pathname matches a wildcard pathname.
  (4) Translate one pathname into another according to a mapping specified
  by a pair of wildcard pathnames.

Proposal (PATHNAME-WILD:NEW-FUNCTIONS):

  Introduce the following three functions:

  1. WILD-PATHNAME-P pathname &optional field-key
  
    Tests a pathname for the presence of wildcard components.  If the first
    argument is not a pathname, string, or file stream an error of type
    TYPE-ERROR is signalled.
  
    If no <field-key> is provided, or the <field-key> is NIL, the result is
    T if <pathname> has any wildcard components, NIL if <pathname> has none.
  
    If a non-null <field-key> is provided, it must be one of :HOST, :DEVICE,
    :DIRECTORY, :NAME, :TYPE, or :VERSION.  In this case, the result is T
    if the indicated component of <pathname> is a wildcard, NIL if the
    component is not a wildcard.  Note that not all implementations
    support wildcards in all fields, according to PATHNAME-COMPONENT-VALUE.


  2. PATHNAME-MATCH-P pathname wildcard

    T if <pathname> matches <wildcard>, otherwise NIL.  The matching rules
    are implementation-defined but should be consistent with the
    DIRECTORY function.  Missing components of <wildcard> default to :WILD.

    If either argument is not a pathname, string, or file stream an error
    of type TYPE-ERROR is signalled.  It is valid for <pathname> to be a
    wild pathname; a wildcard field in <pathname> will only match a
    wildcard field in <wildcard>, i.e. the function is not commutative.
    It is valid for <wildcard> to be a non-wild pathname.


  3. TRANSLATE-PATHNAME source from-wildcard to-wildcard &key

    Translates the pathname <source>, which matches <from-wildcard>, into
    a corresponding pathname <result>, which matches <to-wildcard>, and
    returns <result>.

    The pathname <result> is <to-wildcard> with each wildcard or missing
    field replaced by a portion of <source>.  A "wildcard field" is a
    pathname component with a value of :WILD, a :WILD element of a
    list-valued directory component, or an implementation-defined portion
    of a component, such as the "*" in the complex wildcard string
    "foo*bar" that some implementations support.  An implementation that
    adds other wildcard features, such as regular expressions, must define
    how TRANSLATE-PATHNAME extends to those features.  A "missing field" is
    a pathname component with a value of NIL.

    The portion of <source> that is copied into <result> is implementation
    defined.  Typically it is determined by the user interface conventions
    of the file systems involved.  Usually it is the portion of <source>
    that matches a wildcard field of <from-wildcard> that is in the same
    position as the wildcard or missing field of <to-wildcard>.  If there
    is no wildcard field in <from-wildcard> at that position, then usually
    it is the entire corresponding pathname component of <source>, or in
    the case of a list-valued directory component, the entire corresponding
    list element.  For example, if the name components of <source>,
    <from-wildcard>, and <to-wildcard> are "gazonk", "gaz*", and "h*"
    respectively, then in most file systems, the wildcard fields of the
    name component of <from-wildcard> and <to-wildcard> are each "*", the
    matching portion of <source> is "onk", and the name component of
    <result> is "honk".  However, the exact behavior of TRANSLATE-PATHNAME
    cannot be dictated by the Common Lisp language and must be allowed to
    vary, depending on the user interface conventions of the file systems
    involved.

    During the copying of a portion of <source> into <result>, additional
    implementation-defined translations of alphabetic case or file naming
    conventions might occur, especially when <from-wildcard> and
    <to-wildcard> are for different hosts.

    If any of the first three arguments is not a pathname, string, or file
    stream an error of type TYPE-ERROR is signalled.  It is valid for
    <source> to be a wild pathname; in general this will produce a wild
    result.  It is valid for <from-wildcard> and/or <to-wildcard> to be
    non-wild pathnames.  (PATHNAME-MATCH-P <source> <from-wildcard>) must
    be true or an error is signalled.
    
    There are no specified keyword arguments for TRANSLATE-PATHNAME, but
    implementations are permitted to extend it by adding keyword arguments.
    There is one specified return value from TRANSLATE-PATHNAME;
    implementations are permitted to extend it by returning additional
    values.

    Implementation guideline: one file system performs this operation by
    examining each piece of the three pathnames in turn, where a piece is a
    pathname component or a list element of a structured component such as
    a hierarchical directory.  Hierarchical directory elements in
    <from-wildcard> and <to-wildcard> are matched by whether they are
    wildcards, not by depth in the directory hierarchy.  If the piece in
    <to-wildcard> is present and not wild, it is copied into the result.
    If the piece in <to-wildcard> is :WILD or NIL, the piece in <source> is
    copied into the result.  Otherwise, the piece is <to-wildcard> might be
    a complex wildcard such as "foo*bar" and the piece in <from-wildcard>
    should be wild; the portion of the piece in <source> that matches the
    wildcard portion of the piece in <from-wildcard> replaces the wildcard
    portion of the piece in <to-wildcard> and the value produced is used in
    the result.

  4. Clarify that the functions OPEN (and WITH-OPEN-FILE), PROBE-FILE,
  FILE-WRITE-DATE, FILE-AUTHOR, and TRUENAME only accept non-wildcard
  pathnames and signal an error if given a pathname for which
  WILD-PATHNAME-P returns true.

  5. Clarify that the functions RENAME-FILE, DELETE-FILE, LOAD, and
  COMPILE-FILE have implementation-defined consequences when given a
  wildcard pathname.  Each function might signal an error or might operate
  on all files that match the wildcard pathname.


Examples:

  ;The following examples are not portable.  They are written to run
  ;with particular file systems and particular wildcard conventions.
  ;Other implementations will behave differently.  These examples are
  ;intended to be illustrative, not to be prescriptive.

  (WILD-PATHNAME-P (MAKE-PATHNAME :NAME :WILD)) => T
  (WILD-PATHNAME-P (MAKE-PATHNAME :NAME :WILD) :NAME) => T
  (WILD-PATHNAME-P (MAKE-PATHNAME :NAME :WILD) :TYPE) => NIL
  (WILD-PATHNAME-P (PATHNAME "S:>foo>**>")) => T   ;Lispm
  (WILD-PATHNAME-P (PATHNAME :NAME "F*O")) => T    ;Most places

  ;This example assumes one particular set of wildcard conventions
  ;Not all file systems will run this example exactly as written
  (DEFUN RENAME-FILES (FROM TO)
    (DOLIST (FILE (DIRECTORY FROM))
      (RENAME-FILE FILE (TRANSLATE-PATHNAME FILE FROM TO))))
  (RENAME-FILES "/usr/me/*.lisp" "/dev/her/*.l")
    ;Renames /usr/me/init.lisp to /dev/her/init.l
  (RENAME-FILES "/usr/me/pcl*/*" "/sys/pcl/*/")
    ;Renames /usr/me/pcl-5-may/low.lisp to /sys/pcl/pcl-5-may/low.lisp
    ;In some file systems the result might be /sys/pcl/5-may/low.lisp
  (RENAME-FILES "/usr/me/pcl*/*" "/sys/library/*/")
    ;Renames /usr/me/pcl-5-may/low.lisp to /sys/library/pcl-5-may/low.lisp
    ;In some file systems the result might be /sys/library/5-may/low.lisp
  (RENAME-FILES "/usr/me/foo.bar" "/usr/me2/")
    ;Renames /usr/me/foo.bar to /usr/me2/foo.bar
  (RENAME-FILES "/usr/joe/*-recipes.text" "/usr/jim/cookbook/joe's-*-rec.text")
    ;Renames /usr/joe/lamb-recipes.text to /usr/jim/cookbook/joe's-lamb-rec.text
    ;Renames /usr/joe/pork-recipes.text to /usr/jim/cookbook/joe's-pork-rec.text
    ;Renames /usr/joe/veg-recipes.text to /usr/jim/cookbook/joe's-veg-rec.text

  ;This example assumes one particular set of wildcard conventions
  (PATHNAME-NAME (TRANSLATE-PATHNAME "foobar" "foo*" "*baz")) => "barbaz"
  (PATHNAME-NAME (TRANSLATE-PATHNAME "foobar" "foo*" "*"))    => "foobar"
  (PATHNAME-NAME (TRANSLATE-PATHNAME "foobar" "*"    "foo*")) => "foofoobar"
  (PATHNAME-NAME (TRANSLATE-PATHNAME "bar"    "*"    "foo*")) => "foobar"

  ;Using Unix syntax and the wildcard conventions used by the
  ;particular version of Unix on which I tried this:
  (NAMESTRING
    (TRANSLATE-PATHNAME "/usr/dmr/hacks/frob.l"
                        "/usr/d*/hacks/*.l"
                        "/usr/d*/backup/hacks/backup-*.*"))
   => "/usr/dmr/backup/hacks/backup-frob.l"
  (NAMESTRING
    (TRANSLATE-PATHNAME "/usr/dmr/hacks/frob.l"
                        "/usr/d*/hacks/fr*.l"
                        "/usr/d*/backup/hacks/backup-*.*"))
   => "/usr/dmr/backup/hacks/backup-ob.l"

  ;This is similar to the above example but uses two different hosts,
  ;U: which is a Unix and V: which is a VMS.  Note the translation
  ;of file type and alphabetic case conventions.
  (NAMESTRING
    (TRANSLATE-PATHNAME "U:/usr/dmr/hacks/frob.l"
                        "U:/usr/d*/hacks/*.l"
                        "V:SYS$DISK:[D*.BACKUP.HACKS]BACKUP-*.*"))
   => "V:SYS$DISK:[DMR.BACKUP.HACKS]BACKUP-FROB.LSP"
  (NAMESTRING
    (TRANSLATE-PATHNAME "U:/usr/dmr/hacks/frob.l"
                        "U:/usr/d*/hacks/fr*.l"
                        "V:SYS$DISK:[D*.BACKUP.HACKS]BACKUP-*.*"))
   => "V:SYS$DISK:[DMR.BACKUP.HACKS]BACKUP-OB.LSP"

  ;This example presumes background information described in PATHNAME-LOGICAL
  (DEFUN TRANSLATE-LOGICAL-PATHNAME-1 (PATHNAME RULES)
    (LET ((RULE (ASSOC PATHNAME RULES :TEST #'PATHNAME-MATCH-P)))
      (UNLESS RULE (ERROR "No translation rule for ~A" PATHNAME))
      (TRANSLATE-PATHNAME PATHNAME (FIRST RULE) (SECOND RULE))))
  (TRANSLATE-LOGICAL-PATHNAME-1 "FOO:CODE;BASIC.LISP"
                        '(("FOO:DOCUMENTATION;" "MY-UNIX:/doc/foo/")
                          ("FOO:CODE;"          "MY-UNIX:/lib/foo/")
                          ("FOO:PATCHES;*;"     "MY-UNIX:/lib/foo/patch/*/")))
   => the pathname MY-UNIX:/lib/foo/basic.l

Rationale:

  1,2,3. These three functions provide a standardized interface to the
  idiosyncratic wildcard functionality of each host file system.

  1. WILD-PATHNAME-P makes it possible to detect wild pathnames reliably and
  do something useful (give up, merge out the bothersome components, call
  DIRECTORY for a list of matching pathnames, etc.)

  2,3. TRANSLATE-PATHNAME is needed by many application programs that deal
  with wildcard pathnames.  PATHNAME-MATCH-P and TRANSLATE-PATHNAME are
  needed by logical pathnames.  The PATHNAME-LOGICAL proposal cannot be
  implemented without these features.  Implementing PATHNAME-LOGICAL could
  involve adding additional capabilities to TRANSLATE-PATHNAME, depending
  on the type of file system used, but those capabilities do not need to
  be in the standard.

  4. Since these functions return a value connected with one file, there
  is no meaningful way to extend them to work on wildcard pathnames.  It
  seems best to specify that they signal an error, rather than leaving
  the consequences undefined.

  5. The consequences are proposed to be implementation-defined because
  current practice varies and no one wants to change.

Current Practice:

  Presumably no implementation supports the proposal exactly as stated.
  Symbolics Genera has had similar features under different names for many
  years:

    (SEND pathname :WILD-P) returns a value such as NIL, :NAME, :TYPE,
    etc., indicating the first wild field.

    (SEND pathname :NAME-WILD-P), (SEND pathname :DIRECTORY-WILD-P),
    etc. test individual fields.

    The :TRANSLATE-WILD-PATHNAME, :TRANSLATE-WILD-PATHNAME-REVERSIBLE, and
    :PATHNAME-MATCH messages resemble TRANSLATE-PATHNAME and
    PATHNAME-MATCH-P.

  The Explorer also supports the messages :WILD-P (although it only
  returns NIL or T), :NAME-WILD-P, etc., :TRANSLATE-WILD-PATHNAME, and
  :PATHNAME-MATCH.

  Points 4 and 5 are current practice as far as the authors are aware.
  The Explorer permits DELETE-FILE on a wild pathname, meaning to delete
  all files that match.

Cost to Implementors:

  Many implementations probably have a substrate which is capable of this
  or something similar already. In such cases, it's a relatively small
  matter to add the proposed interface.

  Even in cases where an implementation doesn't have ready code, it's clearly
  better for the implementor to write that code once and for all than to ask
  each user of wildcards to write it.

  Since the detailed behavior is at the implementor's discretion, the cost
  is unlikely to be large.  Some file systems will do all the work and the
  implementor need only provide an interface to the file system or to a
  standard library routine.  For other file systems the implementor has to
  write the actual matching and translation algorithms.

Cost to Users:

  None.  This change is upward compatible.

Cost of Non-Adoption:

  Wild pathnames would continue to be mistaken for ordinary pathnames in
  many situations.  User programs that deal with wildcard pathnames would
  have to operate on implementation-dependent representations and hence
  would not be easily portable.

  The biggest cost is that the logical pathnames proposal would be stymied.

Performance Impact:

  None.

Benefits:

  A more complete set of wildcard pathname operations.  Portable user
  programs that deal with wildcard pathnames will be more consistent
  and reliable.  A portable system construction tool can be written
  and the foundations are laid for a `logical pathname' facility
  (proposed separately in PATHNAME-LOGICAL).

Aesthetics:

  This change would make some portable code less kludgey.

Discussion:

  There was some question about the name. The name PATHNAME-WILD-P
  suggests a ``slot'' of a pathname (like PATHNAME-HOST),
  while WILD-PATHNAME-P suggests a type (like INPUT-STREAM-P).
  The committee was split on what to call it. Since it is more
  like a type than a slot, the name WILD-PATHNAME-P was chosen.

  It's been suggested that WILD-PATHNAME-P and PATHNAME-MATCH-P be allowed
  to return a value other than T to represent "truth", which would
  somehow encode some additional information.

∂23-Jun-89  1234	X3J13-mailer 	issue CLOS-MACRO-COMPILATION, version 5  
Received: from cs.utah.edu by SAIL.Stanford.EDU with TCP; 23 Jun 89  12:34:23 PDT
Received: from defun.utah.edu by cs.utah.edu (5.61/utah-2.1-cs)
	id AA00110; Fri, 23 Jun 89 13:34:46 -0600
Received: by defun.utah.edu (5.61/utah-2.0-leaf)
	id AA03741; Fri, 23 Jun 89 13:34:43 -0600
Date: Fri, 23 Jun 89 13:34:43 -0600
From: sandra%defun@cs.utah.edu (Sandra J Loosemore)
Message-Id: <8906231934.AA03741@defun.utah.edu>
To: x3j13@sail.stanford.edu
Reply-To: cl-compiler@sail.stanford.edu
Subject: issue CLOS-MACRO-COMPILATION, version 5

This is a new version of an issue that was distributed last week.  I
have made some changes to clarify some confusing wording, that are not
supposed to affect the content of the proposal.  I hope this is ready
to vote on now.

Forum:		Compiler
Issue:		CLOS-MACRO-COMPILATION
References:	CLOS chapters 1 & 2 (88-002R)
		CLOS chapter 3 (89-003)
		Issue COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS
		Issue DEFINING-MACROS-NON-TOP-LEVEL
Category:	CLARIFICATION
Edit History:   V1, 10 Mar 1989, Sandra Loosemore
		V2, 13 Mar 1989, Sandra Loosemore
		V3, 21 Mar 1989, Sandra Loosemore (fix error language)
		V4, 11 Jun 1989, Sandra Loosemore (Gregor's amendment)
		V5, 23 Jun 1989, Sandra Loosemore (wording changes per Pitman)
Status:		Ready for release


Problem Description:

Do the CLOS defining macros (DEFCLASS, DEFMETHOD, DEFGENERIC, and
DEFINE-METHOD-COMBINATION) have compile-time side-effects similar
to those for DEFSTRUCT or DEFMACRO?

A part of the problem is that we do not currently have a full
understanding of all the issues involved.  In particular, work on
defining the CLOS meta-object protocol is still in progress.  The goal
of this proposal is to say enough about the behavior of these macros
in the standard so that users can use them portably in compiled code,
but to leave as much of the behavior as possible unspecified to avoid
placing undue restrictions on the meta-object protocol.


Proposal CLOS-MACRO-COMPILATION:MINIMAL:

 State that top-level calls to the CLOS defining macros have the
 following compile-time side-effects.  Any other compile-time behavior
 is explicitly left unspecified.

  DEFCLASS:
  
  * The class name may appear in subsequent type declarations.
  
  * The class name can be used as a specializer in subsequent 
    DEFMETHOD forms.
  
  DEFGENERIC:
  
  * The generic function can be referenced in subsequent DEFMETHOD forms.  

  * DEFGENERIC does not arrange for the generic function to be callable
    at compile time.
  
  DEFMETHOD:
  
  * DEFMETHOD does not arrange for the method to be callable at compile
    time.  If there is a generic function with the same name defined at
    compile time, compiling a DEFMETHOD does not add the method to that 
    generic function.  (That is, the method is added to the generic
    function only when the DEFMETHOD is actually executed.)

    The error-signalling behavior described in the specification of
    DEFMETHOD in CLOS chapter 2 (if the function isn't a generic function
    or if the lambda-list is not congruent) happens only when the defining
    form is executed, not at compile time.

    The forms in EQL specializers are evaluated when the defining form
    is executed.  The compiler is permitted to build in knowledge
    about what the form in an EQL specializer will evaluate to in cases
    where the ultimate result can be syntactically inferred without
    actually evaluating it.

  DEFINE-METHOD-COMBINATION:
  
  * The method combination can be used in subsequent DEFGENERIC forms.  

    The body of a DEFINE-METHOD-COMBINATION form is evaluated no earlier 
    than when the defining macro is executed and possibly as late as 
    generic function invocation time.  The compiler may attempt to
    evaluate these forms at compile time but must not depend on being able
    to do so.

 Rationale:

  The compile-time behavior of DEFCLASS is similar to DEFSTRUCT or
  DEFTYPE.  

  DEFGENERIC and DEFMETHOD are similar to DEFUN, which doesn't add the
  function definition to the compile-time environment.  Since generic
  functions may be freely redefined between compile and run time (just
  like any other function), a method may end up "belonging" to a
  different generic function at load time than at compile time.  This
  is why it is inappropriate to signal errors about congruency problems
  (etc) until the method is actually added to the generic function at
  run time.


Current Practice:

  The items listed under DEFCLASS in proposal MINIMAL are fairly standard
  programming style.

  Flavors does not support compile-time instantiation of classes.  It
  does not make method combinations available at compile-time either, but
  Moon considers that to be a bad design choice.

Cost to implementors:

  Unknown.

Cost to users:

  Unknown, but probably fairly small.

  Wrapping an (EVAL-WHEN (EVAL COMPILE LOAD) ...) around the appropriate
  definitions will make sure they are fully defined at compile-time.
  Alternatively, the definitions could be placed in a separate file,
  which is loaded before compiling the file that depends on those
  definitions.

Benefits:

  Programmers can rely on programs that use the CLOS defining macros 
  being able to compile correctly in all implementations, without having
  to wrap explicit EVAL-WHENs around every macro call.

Discussion:

  This writeup is based on discussions between Moon, Gray, and
  Loosemore, who are mostly in agreement on the things presented in
  proposal MINIMAL.  We have purposely avoided saying anything about
  whether meta-objects representing the classes, methods, etc. get
  created at compile-time, or whether such meta-objects are fully or
  partially defined.  The basic questions addressed by this issue are
  what kinds of things can be defined and then used during compilation
  of the same file that defines them, and what restrictions might apply.

  These proposals are not completely compatible with the meta-object 
  protocol document (89-003).  Gregor Kiczales says:
    No one believes that what is written in draft 10 of the MOP is valid.

  Sandra Loosemore says:
    Although I admit I don't understand all of the issues involved with
    the meta-object protocol, I prefer proposal MINIMAL over 
    NOT-SO-MINIMAL.  I don't think leaving the issue of whether or not
    classes can be instantiated at compile-time unspecified places an
    undue burden on users, and it does leave more freedom for the
    meta-object protocol to decide what the right behavior really is.

  Dick Gabriel notes:
    The question I have about the process going on with respect to the
    CLOS-MACRO-COMPILATION issue is whether the fine-grained behavior of
    CLOS under various compilation/evaluation situations is being
    over-specified. 

    At this stage of the game I worry that we might go a little too far in
    one direction in specification when we are actually engaged in design
    work. This isn't intended to be a criticism of any committees, but I
    would feel a lot more comfortable with a conservative specification
    that defined well-formed programs being loaded or compiled in fresh
    Common Lisps with a pretty simple eval-when model that is easier to
    specify and which makes it easy for all but the hairiest
    compilation-environment-frobbing programs to be written.